#ifndef __BASIC_COMMON_H__
#define __BASIC_COMMON_H__

#include <cstdint>

namespace basic {
constexpr auto M_PIf = 3.14159265358979323846f;
constexpr auto M_2PIf = (6.283185307179586476925286766559f);
constexpr auto M_1_2PIf = (0.15915494309189533576888376337251f);
constexpr auto M_4PIf = (12.566370614359172953850573533118f);
constexpr auto M_8PIf = (25.132741228718345907701147066236f);
constexpr auto M_1_4PIf = (0.07957747154594766788444188168626f);
constexpr auto M_RADIAN_PER_DEGREE = (0.01745329251994329576923690768489f);
constexpr auto M_DEGREE_PER_RADIAN = (57.295779513082320876798154814105f);

template <typename T>
struct DKSRange {
  DKSRange() = default;
  DKSRange(T b, T l) : begin(b), length(l) {
  }
  ~DKSRange() = default;
  T begin;
  T length;
  inline T end() {
    return begin + length - 1;
  }
};

#ifndef M_TO_RADIAN
#define M_TO_RADIAN(degree) (M_RADIAN_PER_DEGREE * (degree))
#endif
#ifndef M_TO_DEGREE
#define M_TO_DEGREE(radian) (M_DEGREE_PER_RADIAN * (radian))
#endif

#ifndef M_SAFE_DELETE
#define M_SAFE_DELETE(p)                                                                                               \
  if (p) {                                                                                                             \
    delete p;                                                                                                          \
    p = nullptr;                                                                                                       \
  }
#endif

#ifndef M_SAFE_DELETES
#define M_SAFE_DELETES(p)                                                                                              \
  if (p) {                                                                                                             \
    delete[] p;                                                                                                        \
    p = nullptr;                                                                                                       \
  }
#endif

#ifndef M_SAFE_FREE
#define M_SAFE_FREE(p)                                                                                                 \
  if (p) {                                                                                                             \
    free(p);                                                                                                           \
    p = nullptr;                                                                                                       \
  }
#endif

#ifndef M_SAFE_DELETE_ELEMENT_CLEAR_MAP
#define M_SAFE_DELETE_ELEMENT_CLEAR_MAP(m)                                                                             \
  for (auto& e : m) {                                                                                                  \
    delete e.second;                                                                                                   \
  }                                                                                                                    \
  m.clear();
#endif

#ifndef M_N2C
#define M_N2C(n) std::to_string(n).c_str()
#endif

#ifndef M_IMPLEMENT
#define M_IMPLEMENT public
#endif

#ifndef M_INTERFACE
#define M_INTERFACE class
#endif

#ifndef M_DELETE_COPY_ASSIGN
#define M_DELETE_COPY_ASSIGN(cls)                                                                                      \
  cls(const cls*) = delete;                                                                                            \
  const cls* operator=(const cls*) = delete;
#endif

#ifndef M_NO_CREATION_AND_DELETION
#define M_NO_CREATION_AND_DELETION(cls)                                                                                \
  cls() = delete;                                                                                                      \
  cls(const cls*) = delete;                                                                                            \
  ~cls() = delete;                                                                                                     \
  const cls* operator=(const cls*) = delete;
#endif

#ifndef M_DEPRECATED
#define M_DEPRECATED
#endif

#ifndef M_ABSTRACT
#define M_ABSTRACT
#endif

#ifndef NS_USE_STD
#define NS_USE_STD using namespace std;
#endif

#ifndef M_B2KiB
#define M_B2KiB(b) ((float)(b >> 10))
#endif

#ifndef M_B2MiB
#define M_B2MiB(b) ((float)(b >> 20))
#endif

#ifndef M_B2GiB
#define M_B2GiB(b) ((float)(b >> 30))
#endif

#define _M_CAT_2_(a, b) a##b
#ifndef M_CAT
#define M_CAT(a, b) _M_CAT_2_(a, b)
#endif
} // namespace basic

#endif
